package com.tencent.txcc.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.tencent.txcc.constants.Constants;
import com.tencent.txcc.domain.*;
import com.tencent.txcc.dto.PhoneRegisterDto;
import com.tencent.txcc.dto.SmsRedisDto;
import com.tencent.txcc.enums.GlobleExceptionCode;
import com.tencent.txcc.feign.LoginService;
import com.tencent.txcc.mapper.*;
import com.tencent.txcc.result.JSONResult;
import com.tencent.txcc.service.IUserAccountService;
import com.tencent.txcc.service.IUserBaseInfoService;
import com.tencent.txcc.service.IUserService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.tencent.txcc.util.AssertUtil;
import com.tencent.txcc.util.StrUtils;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author director
 * @since 2022-09-23
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private LoginService loginService;
    @Autowired
    private IUserBaseInfoService userBaseInfoService;
    @Autowired
    private IUserAccountService userAccountService;
    @Autowired
    private RecommendCodeMapper recommendCodeMapper;
    @Autowired
    private RecommendationRelationshipMapper recommendationRelationshipMapper;
    @Autowired
    private IntegralMapper integralMapper;
    @Autowired
    private UserIntegralLogMapper userIntegralLogMapper;
    @Autowired
    private GrowMapper growMapper;
    @Autowired
    private UserGrowLogMapper userGrowLogMapper;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void register(PhoneRegisterDto phoneRegisterDto) {
        String mobile = phoneRegisterDto.getMobile();
        String password = phoneRegisterDto.getPassword();
        Integer regChannel = phoneRegisterDto.getRegChannel();
        String smsCode = phoneRegisterDto.getSmsCode();

        String redisKey = String.format(Constants.REDIS_PHONE_CONSTANTS, mobile);
        Object obj = redisTemplate.opsForValue().get(redisKey);

        // 判断redis中的短信验证码是否存在
        AssertUtil.isNotNull(obj, GlobleExceptionCode.PARAM_IS_NULL);
        // 判断短信验证码是否正确
        SmsRedisDto smsRedisDto = (SmsRedisDto)obj;
        AssertUtil.isEquals(smsCode, smsRedisDto.getCode(), GlobleExceptionCode.CODE_ERROR);
        // 用mabits-plus
        User user = selectUser(mobile);
        AssertUtil.isNull(user, GlobleExceptionCode.USER_IS_NOT_NULL);

        // 保存login
        JSONResult jsonResult = saveLogin(phoneRegisterDto);
        AssertUtil.isTrue(jsonResult.isSuccess(), GlobleExceptionCode.USER_SAVE_ERROR);
        AssertUtil.isNotNull(jsonResult.getData(), GlobleExceptionCode.USER_SAVE_ERROR);
        Long loginId = Long.valueOf(jsonResult.getData().toString());
        // Long loginId = (Long)jsonResult.getData();

        // 保存信息
        Long userId = saveUser(loginId, phoneRegisterDto);
        initUserBaseInfo(userId, regChannel);
        initUserAccount(userId);

        // 生成一个推荐码，保存起来
        RecommendCode recommendCode = new RecommendCode();
        recommendCode.setUser_id(userId);
        recommendCode.setCode(StrUtils.getComplexRandomString(4));


        // 注册的用户有推荐码
        if (phoneRegisterDto.getCode() != null){
            // 通过code在t_recommend_code表中找到推荐人的id
            recommendCodeMapper.insert(recommendCode);
            // 获取前端传入的推荐码
            String code = phoneRegisterDto.getCode();
            // 判断推荐人的ID是否出现过t_recommendation_relationship
//            AssertUtil.isNull(code, GlobleExceptionCode.USER_SAVE_ERROR);
            RecommendationRelationship findByCode = recommendationRelationshipMapper.findByCode(code);
            AssertUtil.isNull(findByCode, GlobleExceptionCode.ALREDY_REGISTER);
            // 获取推荐人的id
            Long user_id = recommendCodeMapper.findUserIdByCode(code);
            // 将推荐人id和注册人id和推荐人推荐码保存经t_recommendation_relationship中
            RecommendationRelationship recommendationRelationship = new RecommendationRelationship();
            // 推荐人id
            recommendationRelationship.setUserId(user_id);
            // 注册人id
            recommendationRelationship.setRegisterUserId(userId);
            // 推荐人推荐码
            recommendationRelationship.setCode(code);
            recommendationRelationshipMapper.insert(recommendationRelationship);


            // 将推荐人的积分+10分
            // 通过推荐人id找到推荐人的integral
            Integer integralScore = integralMapper.getIntegralByUserId(user_id);
            integralScore = integralScore + 10;
            // 通过user_id修改integral
            Integral integral = new Integral();
            integral.setIntegral(integralScore);
            integral.setUser_id(user_id);
            integralMapper.updateIntegralByUserId(integral);

            // 添加到t_user_integral_log日志表
            UserIntegralLog userIntegralLog = new UserIntegralLog();
            userIntegralLog.setUserId(user_id);
            userIntegralLog.setMessage("推荐注册积分+10");
            userIntegralLogMapper.insert(userIntegralLog);

            // 通过user_id获取到对应的成长值
            Integer growScore = growMapper.getGrowByUserId(user_id);
            growScore = growScore +10;
            // 通过user_id修改grow
            Grow grow = new Grow();
            grow.setUser_id(user_id);
            grow.setGrow(growScore);
            growMapper.updateGrowByUserId(grow);

            // 保存到成长值日志
            UserGrowLog userGrowLog = new UserGrowLog();
            userGrowLog.setCreate_time(new Date().getTime());
            userGrowLog.setUser_id(user_id);
            userGrowLog.setFromReason("推荐人注册加成长值");
            userGrowLog.setScore(10);
            userGrowLogMapper.insert(userGrowLog);


        }else {
            recommendCodeMapper.insert(recommendCode);
        }

    }

    @Override
    public String selectGrade(Long user_id) {
        Integer grow = growMapper.getGrowByUserId(user_id);
        String grade = "";
        if (grow >= 0 && grow <= 99){
            grade = "青铜";
        } else if (grow >= 100 && grow <= 299){
            grade = "白银";
        } else if (grow >= 300 && grow <= 599){
            grade = "黄金";
        } else if (grow >= 600 && grow <= 999){
            grade = "铂金";
        } else if (grow >= 1000 && grow <= 1499){
            grade = "钻石";
        } else if (grow >= 1500 && grow <= 2499){
            grade = "大师";
        } else if (grow >= 2500){
            grade = "王者";
        }
        return grade;
    }


    private Long saveUser(Long loginId, PhoneRegisterDto phoneRegisterDto){
        User user = new User();
        user.setCreateTime(new Date().getTime());
        user.setLoginId(loginId);
        user.setNickName(phoneRegisterDto.getMobile());
        user.setPhone(phoneRegisterDto.getMobile());
        insert(user);
        return user.getId();
    }

    private void initUserBaseInfo(Long userId, Integer regChannel){
        UserBaseInfo userBaseInfo = new UserBaseInfo();
        userBaseInfo.setId(userId);
        userBaseInfo.setRegChannel(regChannel);
        userBaseInfo.setCreateTime(new Date().getTime());
        userBaseInfoService.insert(userBaseInfo);
    }

    private void initUserAccount(Long userId){
        UserAccount userAccount = new UserAccount();
        userAccount.setCreateTime(new Date().getTime());
        userAccount.setPassword("696969");
        userAccount.setId(userId);
        userAccountService.insert(userAccount);
    }

    private JSONResult saveLogin(PhoneRegisterDto phoneRegisterDto){
        Login login = new Login();
        login.setUsername(phoneRegisterDto.getMobile());
        login.setPassword(phoneRegisterDto.getPassword());
        login.setType(Login.USER_TYPE);
        login.setEnabled(Login.ENABLE);
        return loginService.saveOrUpdate(login);
    }

    // 封装一个方法通过手机号找到user
    private User selectUser(String mobile){
        Wrapper<User> wrapper = new EntityWrapper<>();
        wrapper.eq("phone", mobile);
        return selectOne(wrapper);
    }
}

